from PySide6.QtCore import QThread, Signal
import numpy as np
import time


class ScanWorker(QThread):
    # 定义信号用于主线程通信
    update_position = Signal(float, float)      # 当前坐标更新 (x, y)
    update_result = Signal(int, int, float)     # 测试结果更新 (行, 列, 电流值)
    finished = Signal()                         # 扫描完成

    def __init__(self, motor, source, stage_x, stage_y, testing_flag, paused_flag, tested_points=0):
        # :param motor: 电机控制器对象
        # :param source: 源表控制器对象
        # :param stage_x: x 轴设置字典（单位 mm）
        # :param stage_y: y 轴设置字典（单位 mm）
        # :param testing_flag: 外部函数，用于检测是否继续运行
        # :param paused_flag: 外部函数，用于检测是否处于暂停
        # :param tested_points: 已完成的点数（从此点数继续）
        super().__init__()
        self.motor = motor
        self.source = source
        self.stage_x = stage_x
        self.stage_y = stage_y
        self.testing_flag = testing_flag
        self.paused_flag = paused_flag
        self.tested_points = tested_points

    def run(self):
        """线程主函数，负责逐点扫描并采集数据"""
        x_start = self.stage_x['start']
        x_end = self.stage_x['end']
        x_step = self.stage_x['step'] / 1000  # μm → mm

        y_start = self.stage_y['start']
        y_end = self.stage_y['end']
        y_step = self.stage_y['step'] / 1000  # μm → mm

        x_points = np.arange(x_start, x_end + x_step, x_step)
        y_points = np.arange(y_start, y_end + y_step, y_step)

        total_x = len(x_points)
        total_y = len(y_points)

        # 计算起始点位置
        start_iy = self.tested_points // total_x
        start_ix = self.tested_points % total_x

        for iy in range(start_iy, total_y):
            for ix in range(start_ix if iy == start_iy else 0, total_x):
                # 检查是否被主线程要求终止
                if not self.testing_flag():
                    self.finished.emit()
                    return

                # 如果处于暂停状态，则持续等待，直到恢复
                while self.paused_flag():
                    if not self.testing_flag():
                        self.finished.emit()
                        return
                    time.sleep(0.1)

                x = x_points[ix]
                y = y_points[iy]
                # 执行电机移动
                self.motor.move_xy(x, y)
                self.motor.wait_for_motion_done(0)
                self.motor.wait_for_motion_done(1)

                # 向主线程发送当前位置更新信号
                self.update_position.emit(x, y)

                # 执行采样并发送结果
                result = self.source.perform_sampling()
                if result:
                    # current = self.source.read_current()
                    self.update_result.emit(iy, ix, result["current"])

        # 扫描任务完成，通知主线程
        self.finished.emit()
